home *** CD-ROM | disk | FTP | other *** search
- ;
- ; This file contains some macro definitions.
- ;
- include utils.mac
- .xlist
- .xcref ?ASET,?AVAL,?PUSH,?POP,?TOS,?J,?JNF,?LBL,?mx
- .xcref ?if,?while,?forever
- .xcref ?brkcnt,?brklab
- .xcref ?dbsp,?STK0,?STKT0,?STKTOPT,?STKTOP,?CTR
- ?mx MACRO a,b,c,d,e,f ;; Macro to allow multi statements on line
- a
- b
- c
- d
- e
- f
- ENDM
- ?mx <?if equ 1>,<?while equ 2>,<?forever equ 3> ; Declare stack types
- ?repeat equ 4
- ?mx ?brkcnt=-1,?brklab=-1 ; Useful variables for BREAK
- ?mx IF2,<.ERRNZ ?dbsp ;; Nesting error>,ENDIF ; Check for nesting errors:
- ; Initialise variables for stack handling:
- ?mx ?dbsp=0,?STK0=0,?STKT0=0,?STKTOP=-1,?STKTOPT=-1,?CTR=0
-
- ?ASET MACRO v,l,n
- .xcref v&l
- v&l = n ;; Set an 'array' variable.
- ENDM
-
- ?AVAL MACRO n,v,l
- n = v&l ;; Read an 'array' variable.
- ENDM
-
- ?PUSH MACRO n,t ;; Push new value onto stack.
- ?mx ?dbsp=?dbsp+1,?STKTOP=n,?STKTOPT=t
- ?ASET ?STK,%?dbsp,n
- ?ASET ?STKT,%?dbsp,t
- ENDM
-
- ?POP MACRO ;; Pop top element off stack.
- ?mx <IF ?dbsp GT 0>,?dbsp=?dbsp-1,ENDIF
- ?AVAL ?STKTOP,?STK,%?dbsp
- ?AVAL ?STKTOPT,?STKT,%?dbsp
- ENDM
-
- ?TOS MACRO t ;; Check type of top of stack.
- .ERRE ?dbsp ; Stack underflow
- .ERRNZ ?STKTOPT NE t ; Stack type mismatch
- ENDM
-
- ?JNF MACRO c,t,n ;; Produce far conditional jump - beware too many n's.
- local L
- .xcref L
- j&c L
- jmp t&n
- L LABEL NEAR
- ENDM
-
- ?J MACRO c,t,n ;; Jump conditional to t&n
- j&c t&n
- ENDM
-
- ?LBL MACRO t,n ;; Label t&n
- .xcref t&n
- IFNDEF t&n
- t&n LABEL NEAR
- ELSE
- IF t&n EQ $
- t&n LABEL NEAR
- ENDIF
- ENDIF
- ENDM
-
- ;
- ; Now I have some stack handling here are the REAL macros.
- ;
- .IF MACRO f,x,y
- IFNB <f>
- IFDIF <f>,<far>
- IFDIF <f>,<FAR>
- IFDIF <f>,<Far>
- .ERRNB <y> ;; Too many args to .IF
- .IF <>,<f>,<x>
- EXITM
- ENDIF
- ENDIF
- ENDIF
- ENDIF
- ?PUSH ?CTR,?if
- ?CTR=?CTR+1
- IFB <y> ;; Only 1 parm - must be condition.
- IFB <f>
- ?J n&x,?E,%?STKTOP
- ELSE ;; Far jump on not x
- ?JNF <x>,?E,%?STKTOP
- ENDIF
- ELSE
- ;; Expand x into a list of instructions:
- ?mx x
- IFB <f>
- ?J n&y,?E,%?STKTOP
- ELSE
- ?JNF <y>,?E,%?STKTOP
- ENDIF
- ENDIF
- ENDM
- .ELSE MACRO ;; Doesn't need a far option.
- ?TOS ?if
- ?J <>,?F,%?STKTOP
- ?LBL ?E,%?STKTOP
- ENDM
- .FI MACRO
- ?TOS ?if
- ?LBL ?E,%?STKTOP
- ?LBL ?F,%?STKTOP
- ?POP
- ENDM
-
- ; All loops have a repeat label ?R... at the top and a break ?B... at the foot
-
- .FOREVER MACRO d ;; Infinite loop - ignores parameter
- .ERRDIF <d>,<DO> ; Keyword DO expected
- ?PUSH ?CTR,?forever
- ?CTR = ?CTR+1
- ?LBL ?R,%?STKTOP
- ENDM
-
- .REPEAT MACRO ;; Condition at bottom - no parameters here.
- ?PUSH ?CTR,?repeat
- ?CTR = ?CTR+1
- ?LBL ?R,%?STKTOP
- ENDM
-
- ; .UNTIL cc is just: BREAK Ncc inside an infinite loop:
- .UNTIL MACRO x
- .ERRB <x> ; Condition expected .UNTIL
-
- IF ?STKTOPT EQ ?repeat
- IFB <f>
- ?J n&x,?R,%?STKTOP
- ELSE
- ?JNF x,?R,%?STKTOP
- ENDIF
- ?LBL ?B,%?STKTOP
- ?POP
- ELSE
- .ERR Unmatched .UNTIL
- ENDIF
- ENDM
-
- ; WHILE cc DO is just: BREAK Ncc inside an infinite loop:
- .WHILE MACRO f,x,y,z
- IFNB <f>
- IFDIF <f>,<far>
- IFDIF <f>,<FAR>
- IFDIF <f>,<Far>
- .ERRNB <z> ;; Too many args to .WHILE
- .WHILE <>,<f>,<x>,<y>
- EXITM
- ENDIF
- ENDIF
- ENDIF
- ENDIF
- .ERRB <y> ; Condition or DO expected
- ?PUSH ?CTR,?while
- ?CTR = ?CTR+1
- ?LBL ?R,%?STKTOP
- IFB <z> ;; x is condition, y is 'DO'
- .ERRDIF <y>,<DO> ; DO expected
- .ERRB <x> ; No condition for .WHILE
- IFB <f>
- ?J n&x,?B,%?STKTOP
- ELSE
- ?JNF x,?B,%?STKTOP
- ENDIF
- ELSE
- .ERRDIF <z>,<DO> ; DO expected
- ?mx x
- IFB <f>
- ?J n&y,?B,%?STKTOP
- ELSE
- ?JNF y,?B,%?STKTOP
- ENDIF
- ENDIF
- ENDM
-
- .OD MACRO ;; End of loop.
- IF (?STKTOPT EQ ?forever) OR (?STKTOPT EQ ?while)
- ?J <>,?R,%?STKTOP
- ?LBL ?B,%?STKTOP
- ?POP
- ELSE
- .ERR ; Nesting error
- ENDIF
- ENDM
-
- .BREAK MACRO f,cc ;; Break from loop - this may involve searching down stack!
- IFNB <f>
- IFDIF <f>,<far>
- IFDIF <f>,<FAR>
- IFDIF <f>,<Far>
- .ERRNB <cc> ;; Too many args to .BREAK
- .BREAK <>,<f>
- EXITM
- ENDIF
- ENDIF
- ENDIF
- ENDIF
- ?brkcnt=?dbsp
- ?brklab=-1
- .ERRE ?dbsp ; BREAK outside all loops
- REPT ?dbsp
- ?AVAL ?brklab,?STKT,%?brkcnt
- IF (?brklab EQ ?forever) OR (?brklab EQ ?while) OR (?brklab EQ ?repeat)
- ?AVAL ?brklab,?STK,%?brkcnt
- IFB <f>
- ?J <cc>,?B,%?brklab
- ELSE
- ?JNF n&cc,?B,%?brklab
- ENDIF
- EXITM
- ENDIF
- ?brkcnt = ?brkcnt - 1
- .ERRE ?brkcnt ; BREAK outside all loops
- ENDM
- ENDM
- qlist ;; Restores listing.
-